﻿
using Microsoft.Net.Http.Headers;
using mozhi.smarterp.Gateway.Internal.Dtos;
using Newtonsoft.Json;

namespace mozhi.smarterp.Gateway.Internal.Middlewares.authorization
{
    public class AuthorizationMiddleware
    {
        private RequestDelegate _next;
        private IConfiguration _configuration;
        private IHttpClientFactory _httpClientFactory;

        public AuthorizationMiddleware(RequestDelegate next, IConfiguration configuration, IHttpClientFactory httpClientFactory)
        {
            _next = next;
            _configuration = configuration;
            _httpClientFactory = httpClientFactory;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            var whiteList = _configuration.GetSection("AuthorizeWhiteList").Get(typeof(string[])) as string[];

            if(whiteList==null)
                throw new ArgumentNullException(nameof(whiteList));

            var requestPath = GetDownstreamPath(context.Request.Path.ToString());

            if(whiteList.Contains(requestPath))
            {
                await _next(context);
                return;
            }

            var requestMethod = context.Request.Method.ToString();

            var accessToken = context.Request.Headers.Authorization.ToString();

            var userAuthorizedUrls = await GetUserAuthorizedUrlsAsync(accessToken);

            var matchUrl = userAuthorizedUrls.FirstOrDefault(x => x.Path == requestPath.ToLower() && x.Method == requestMethod.ToLower());

            //if (matchUrl == null)
            //{
            //    context.Response.StatusCode = StatusCodes.Status401Unauthorized; //(new { Code = 401, Message = "unauthorized", Result = string.Empty });
            //    return;
            //}

            await _next(context);
        }

        #region
        private async Task<List<UserAuthorizedUrlDto>> GetUserAuthorizedUrlsAsync(string accessToken)
        {
            var autherServer = _configuration["AuthServer:Authority"];

            var url = autherServer.EndsWith("/") ? autherServer + "api/identity/users/authorized-urls" : autherServer + "/api/identity/users/authorized-urls";

            var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, url)
            {
                Headers =
                {
                    { HeaderNames.Accept, "application/json" },
                    { HeaderNames.Authorization, accessToken }
                }
            };

            var httpClient = _httpClientFactory.CreateClient();
            var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage);

            var result = new List<UserAuthorizedUrlDto>();

            if (httpResponseMessage.IsSuccessStatusCode)
            {
                var content = await httpResponseMessage.Content.ReadAsStringAsync();

                result = JsonConvert.DeserializeObject<List<UserAuthorizedUrlDto>>(content);
            }

            return result ?? new List<UserAuthorizedUrlDto>();
        }

        private string GetDownstreamPath(string path)
        {
            var splits = path.Split('/').ToList().Where(x=>!string.IsNullOrWhiteSpace(x)).ToList();

            if (splits.Count == 1)
                return path;

            return path.Replace("/" + splits[0], "").ToLower();
        }
        #endregion
    }
}
